#ifndef UNITY_SHADER_DT_UTIL_INCLUDED
#define UNITY_SHADER_DT_UTIL_INCLUDED
    // ==================================================================
    //
    // 引用的文件
    //
    // ==================================================================   
    // DT_URP_MODE _with_pragmas
    #ifdef DT_URP_MODE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"   
    #else
        #include "UnityCG.cginc"
    #endif

    //所有模式都使用我自己的。 use Self Mode
    // #define DT_USE_SELF
    // ==================================================================
    //
    // 精度总控制
    //
    // ==================================================================
        typedef float        DTfloat;
        typedef float2       DTfloat2;
        typedef float3       DTfloat3;
        typedef float4       DTfloat4;

        typedef float2x2     DTfloat2x2;
        typedef float2x3     DTfloat2x3;
        typedef float2x4     DTfloat2x4;

        typedef float3x2     DTfloat3x2;
        typedef float3x3     DTfloat3x3;
        typedef float3x4     DTfloat3x4;
        typedef float4x3     DTfloat4x3;
        typedef float4x4     DTfloat4x4;
        
        #define DT_INV2PI  0.15915494309f //UNITY_INV_TWO_PI
        #define SAFE_MIN 0.0000001
        #define SAFE_MIN2 DTfloat2(0.0000001,0.0000001)
        #define SAFE_COLOR_MIN 0.003921568627451
        #define SAFE_COLOR_MAX 0.996078431372549
        #define SAFE_FLOAT_MIN -60000
        #define SAFE_FLOAT_MAX 60000

        #define DT_SAFE_VALUE(v) (abs(v) < SAFE_MIN ? SAFE_MIN : (v))
        #define DT_SAFE_VALUE2(v) (abs(v.xy) < SAFE_MIN2 ? SAFE_MIN2 : (v.xy))
        #define SAFE_COLOR(col) (clamp((col), SAFE_COLOR_MIN, SAFE_COLOR_MAX))

    // ==================================================================
    //
    // 自定义bit=>指定位范围
    //
    // ==================================================================
        static const int dtBitMaskHalf[15] = 
        { 
              0x0,     0x1,    0x3,    0x7,//1
              0xF,    0x1F,   0x3F,   0x7F,//2
             0xFF,   0x1FF,  0x3FF,  0x7FF,//3
            0xFFF,  0x1FFF, 0x3FFF 
        };
        static const int dtBitMaskInt[31] =
        {
                  0x0,        0x1,        0x3,        0x7,//1
                  0xF,       0x1F,       0x3F,       0x7F,//2
                 0xFF,      0x1FF,      0x3FF,      0x7FF,//3
                0xFFF,     0x1FFF,     0x3FFF,     0x7FFF,//4 
               0xFFFF,    0x1FFFF,    0x3FFFF,    0x7FFFF,//5
              0xFFFFF,   0x1FFFFF,   0x3FFFFF,   0x7FFFFF,//6
             0xFFFFFF,  0x1FFFFFF,  0x3FFFFFF,  0x7FFFFFF,//7
            0xFFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF//,0x7FFFFFFF//8
        };  
        //此处我不防数组溢出，因为我假设len不会超过15，剔除掉符号位，因为符号位右移会出现不一样的结果，所以不会溢出。如果被滥用，让它提交错误
        int dt_GetBit(int value,int index,int len)
        {
            const int mask = dtBitMaskHalf[len]; //(1 << len) - 1;
            return value >> index & mask;
        }
        // DTfloat dt_GetBit(int value,int index,int len)
        // {
        //     const int mask = dtBitMaskHalf[len]; //(1 << len) - 1;
        //     const int f = value >> index & mask;
        //     return  (DTfloat)f;
        // }
        // bool dt_GetBit(int value,int index)
        // {
        //     const int mask = value >> index & 0x1;
        //     return mask > 0;
        // }
    // ==================================================================
    //
    // 自定义Time
    //
    // ==================================================================
        #ifdef DT_USE_CUSTOM_TIME

            #define YF_CUSTOM_TIME_PROP dt_customTime            
            // Shader.SetGlobalFloat("dt_customTime",程序输入的递进变量 % 10f); 
            // 取模10f是想永远得到0-10秒间的循环，浮点值,也能是毫秒，毫秒这里还需要乘个0.001转换一下
            // 我把速度约束了一下精度，就怕美术调整的时候，来个精度外的数值，到时候都查不出问题再那里。
            // 把一个面片放大100倍（还在UI上），调整偏移的时候，原来的1，就变成0.0001 * 0.01,这个明显是不能接受的精度
            uniform float YF_CUSTOM_TIME_PROP;
            #define YF_TIME2 DTfloat2(YF_CUSTOM_TIME_PROP,YF_CUSTOM_TIME_PROP)
            #define YF_TIME YF_CUSTOM_TIME_PROP 
        #else
            #define YF_TIME2 (_Time.yy)
            #define YF_TIME (_Time.y) 
        #endif

        #define YF_SAFE_SPEED(speed) (floor(speed * 100.0) * 0.01)
        #define dt_AutoValue(speed)  (frac(YF_TIME * YF_SAFE_SPEED(speed)))
        #define dt_AutoUV(uSpeed,vSpeed)  (frac(YF_TIME2 * YF_SAFE_SPEED(DTfloat2(uSpeed,vSpeed))))



    // ==================================================================
    //
    // 定义采样器
    //
    // ================================================================== 
    #ifdef DT_URP_MODE
        #define DT_SAMPLER2D(tex) TEXTURE2D(tex);SAMPLER(sampler##tex)
        
        #define DT_TEX_SIZE(tex) float4  tex##_TexelSize
        #define DT_TEX_ST(tex) float4  tex##_ST

        #define DT_TEX2D(tex,uv) (SAMPLE_TEXTURE2D(tex, sampler##tex, uv))
        
        SAMPLER(sampler_linear_repeat);
        SAMPLER(sampler_linear_clamp);
        SAMPLER(sampler_point_repeat);
        SAMPLER(sampler_point_clamp);
    #endif

    // ==================================================================
    //
    // 自定义的一些常用函数 
    //
    // ==================================================================         
        #define DTSAFEINT01(val) (step(0.5,val)) //大于0.5返回1，否则返回0
        #define DTSAFEINT01_INV(val) (step(val,0.5)) //大于0.5返回0，否则返回1
        #define DT_SAFE_IF(b,v0,v1)  (DTSAFEINT01(b) * v0 + DTSAFEINT01_INV(b) * v1)

        DTfloat dt_Ramp_float(DTfloat val, DTfloat IMIN, DTfloat IMAX, DTfloat OMIN, DTfloat OMAX) 
        { 
            return OMIN + ((val - IMIN) * (OMAX - OMIN)) / DT_SAFE_VALUE(IMAX - IMIN);
        }        
        DTfloat dt_Ramp01_float(DTfloat val, DTfloat IMIN, DTfloat IMAX)
        {
            return (val - IMIN) / DT_SAFE_VALUE(IMAX - IMIN);
        }
    //==========================================================================================================================================================
    //
    //  UV变换的矩阵
    //
    //==========================================================================================================================================================
        // |0.5,0.0,0.5| |cos,-sin,0.0| |2.0,0.0,-1.0| |scx,0.0, ofx|
        // |0.0,0.5,0.5|*|sin, cos,0.0|*|0.0,2.0,-1.0|*|0.0,scy, ofy|
        // |0.0,0.0,1.0| |0.0, 0.0,1.0| |0.0,0.0, 1.0| |0.0,0.0, 1.0|
        float3x3 GetUVMatrix(float2 pos,float2 scale,float normalizedValue)
        {
            float radians = normalizedValue * 3.14159265359 * 2.0;
            float cosv = cos(radians);
            float sinv = sin(radians);
            float3x3 rotMatr = float3x3
            (
                cosv, -sinv, 0.0f,
                sinv, cosv, 0.0f,
                0.0f, 0.0f, 1.0f
            );
            float3x3 halfMatr = float3x3
            (
                0.5f, 0.0f, 0.0f,
                0.0f, 0.5f, 0.0f,
                0.0f, 0.0f, 1.0f
            );
            // 先计算左边 3 个矩阵的乘积
            float3x3 CenterMatr = float3x3
            (
                2.0f, 0.0f, 0.0f,
                0.0f, 2.0f, 0.0f,
                -1.0f, -1.0f, 1.0f
            );
            float3x3 TranMatr = float3x3
            (
                scale.x, 0.0f, 0.0f,
                0.0f, scale.y, 0.0f,
                pos.x, pos.y, 1.0f
            );
            return mul(TranMatr, mul(halfMatr, mul(rotMatr, CenterMatr)));
        }

        float3x3 GetUVMatrix(float3x3 inputMatr,float angle)
        {
            float radians = angle * 3.14159265359 * 2.0;
            float cosv = cos(radians);
            float sinv = sin(radians);
            float3x3 rotMatr = float3x3
            (
                cosv, sinv, 0.0f,
                -sinv, cosv, 0.0f,
                0.0f, 0.0f, 1.0f
            );
            float3x3 halfMatr = float3x3
            (
                0.5f, 0.0f, 0.5f,
                0.0f, 0.5f, 0.5f,
                0.0f, 0.0f, 1.0f
            );  

            return mul(halfMatr, mul(rotMatr, inputMatr));
        }

        DTfloat2 dt_SetMatrixUVWork(DTfloat2 _uv, float angle,DTfloat3 matrM0, DTfloat3 matrM1)
        {
            const DTfloat3x3 UVMatrix = DTfloat3x3 (
                matrM0.x, matrM0.y, matrM0.z,
                matrM1.x, matrM1.y, matrM1.z,
                0.0, 0.0, 1.0 
            );
            return mul(GetUVMatrix(UVMatrix,angle), DTfloat3(_uv, 1.0)).xy;
        }
        
        DTfloat2 dt_SetMatrixUVWork(DTfloat2 _uv, DTfloat3 matrM0, DTfloat3 matrM1)
        {
            /*
            // 算法注释 矩阵，通过矩阵乘法，实现uv的旋转，缩放，偏移。可以把算法放到customEditor里，不占用shader本身的算力
            // float angle = _angle * Mathf.Deg2Rad;
            // float cosv = cos(angle);
            // float sinv =  sin(angle);
            // |0.5,0.0,0.5| |cos,-sin,0.0| |2.0,0.0,-1.0| |scx,0.0, ofx|
            // |0.0,0.5,0.5|*|sin, cos,0.0|*|0.0,2.0,-1.0|*|0.0,scy, ofy|
            // |0.0,0.0,1.0| |0.0, 0.0,1.0| |0.0,0.0, 1.0| |0.0,0.0, 1.0|
            */
            const DTfloat3x3 UVMatrix = DTfloat3x3 (
                matrM0.x, matrM0.y, matrM0.z,
                matrM1.x, matrM1.y, matrM1.z,
                0.0, 0.0, 1.0
            );
            return mul(UVMatrix, DTfloat3(_uv, 1.0)).xy;
        }

        // #define DT_INV2PI  0.15915494309f //UNITY_INV_TWO_PI
        DTfloat2 GetPolarCoord(DTfloat2 _uv, DTfloat2 Center)
        {
            const DTfloat2 delta = _uv - Center;
            const DTfloat radius = length(delta) * 2.0;
            const DTfloat angle = atan2(delta.x, delta.y) * 0.15915494309f;
            // 不同以往的改动  重要改动
            return float2(radius,angle);
        }

        DTfloat3 GetSceneCoord(DTfloat4 positionHCS)
        {
            const DTfloat4 tmp = ComputeScreenPos(positionHCS);            
            return DTfloat3(tmp.xy / DT_SAFE_VALUE(tmp.w),tmp.w);
        }
    //==========================================================================================================================================================
    //
    //   
    //  根据输入，获取单通道内容
    //   
    //
    //==========================================================================================================================================================
        DTfloat3 GetOneChannle(DTfloat3 col,int csw)
        {           
            const int _sw = csw & 3;
            if (_sw == 0) return col;
            if (_sw == 1) return col.rrr;
            if (_sw == 2) return col.ggg;
            return col.bbb;
        }


    //==========================================================================================================================================================
    //
    //  Blend PS混合模式
    //  layer0 是下图层
    //  layer1 是上图层
    //
    //==========================================================================================================================================================
        DTfloat4 dt_ToInputColor(DTfloat4 col)
        {
            #ifdef UNITY_COLORSPACE_GAMMA
                return col; 
            #else
                const DTfloat INV_GAMMA = 1.0 / 2.2;
                return pow(col,INV_GAMMA);
            #endif
        }
        //输出结果时,把统一颜色正确输出
        DTfloat4 dt_ToOutputColor(DTfloat4 color)
        {
            #ifdef UNITY_COLORSPACE_GAMMA
                return color;
            #else
                const DTfloat GAMMA = 2.2;
                return pow(color,GAMMA);
            #endif
        }
        // 应用透明度混合，通过上面计算过的RGB，最后都需要经过这个计算才能得到和PS一样的效果
        DTfloat3 DT_PS_ApplyAlphaBlend(DTfloat4 f, DTfloat4 layer0, DTfloat4 layer1) {
            return f.rgb * layer1.a + layer0.rgb * (1.0 - layer1.a);
            //A=A1+A2-A1*A2*255
        }
    // ==================================================================
    //
    // 普通
    //
    // ==================================================================
        DTfloat3 DT_PS_NORMAL(DTfloat4 layer0, DTfloat4 layer1) {
            DTfloat d =saturate(layer0.a + layer1.a - layer0.a * layer1.a );//  layer1.a + layer0.a * (1.0 - layer1.a); //
            return layer1.rgb * d + (1.0 - d) * (layer0.rgb);
        }
    // ==================================================================
    //
    // 变亮
    //
    // ==================================================================
        DTfloat3 DT_PS_LIGHTEN(DTfloat4 layer0, DTfloat4 layer1) {
            return max(layer0.rgb, layer1.rgb);
        }
        DTfloat3 DT_PS_LIGHTEN(DTfloat3 layer0, DTfloat3 layer1) {
            return max(layer0.rgb, layer1.rgb);
        }
    // ==================================================================
    //
    // 变暗
    //
    // ==================================================================
        DTfloat3 DT_PS_DARKEN(DTfloat4 layer0, DTfloat4 layer1) {
            return min(layer0.rgb, layer1.rgb);
        }
        DTfloat3 DT_PS_DARKEN(DTfloat3 layer0, DTfloat3 layer1) {
            return min(layer0.rgb, layer1.rgb);
        }
    // ==================================================================
    //
    // 正片叠底
    //
    // ==================================================================
        DTfloat3 DT_PS_MULTIPLY(DTfloat4 layer0, DTfloat4 layer1) {
            return layer1.rgb * layer0.rgb;
        }
        DTfloat3 DT_PS_MULTIPLY(DTfloat3 layer0, DTfloat3 layer1) {
            return layer1 * layer0;
        }
    // ==================================================================
    //
    // 滤色 1 - (1 - a) * (1 - b)
    //
    // ==================================================================
        DTfloat3 DT_PS_SCREEN(DTfloat4 layer0, DTfloat4 layer1) {
            return layer0.rgb + layer1.rgb - layer0.rgb * layer1.rgb;
        }
        DTfloat3 DT_PS_SCREEN(DTfloat3 layer0, DTfloat3 layer1) {
            return layer0.rgb + layer1.rgb - layer0.rgb * layer1.rgb;
        }
    // ==================================================================
    //
    // 颜色加深
    //
    // ================================================================== 
        DTfloat3 DT_PS_COLOR_BURN(DTfloat4 layer0, DTfloat4 layer1) {
            DTfloat4 col = SAFE_COLOR(layer1); //防除0
            return layer0.rgb - (DTfloat3(1.0,1.0,1.0) - layer0.rgb) * (DTfloat3(1.0,1.0,1.0) - layer1.rgb) / col.rgb;
        } 
        DTfloat3 DT_PS_COLOR_BURN(DTfloat3 layer0, DTfloat3 layer1) {        
            return DT_PS_COLOR_BURN(DTfloat4(layer0.rgb,1), DTfloat4(layer1.rgb,1));
        }
    // ==================================================================
    //
    // 颜色减淡
    //
    // ================================================================== 
        DTfloat3 DT_PS_COLOR_DODGE(DTfloat4 layer0, DTfloat4 layer1) {
            return min(1.0, layer0.rgb / (DTfloat3(1.0,1.0,1.0) - layer1.rgb));
        }
        DTfloat3 DT_PS_COLOR_DODGE(DTfloat3 layer0, DTfloat3 layer1) {
            return min(1.0, layer0.rgb / (DTfloat3(1.0,1.0,1.0) - layer1.rgb));
        }
    // ==================================================================
    //
    // 经典颜色减淡
    //
    // ==================================================================
        DTfloat3 DT_PS_CLASSIC_COLOR_DODGE(DTfloat4 layer0, DTfloat4 layer1)
        {
            const DTfloat3 a = layer0.rgb * layer0.a;
            const DTfloat3 b = layer1.rgb * layer1.a;
            const DTfloat3 col = SAFE_COLOR((DTfloat3(1.0,1.0,1.0) - a.rgb)); //防除0
            return b.xyz + a.xyz * layer1.xyz / col.xyz;
        }
        DTfloat3 DT_PS_CLASSIC_COLOR_DODGE(DTfloat3 layer0, DTfloat3 layer1)
        {
            return DT_PS_CLASSIC_COLOR_DODGE(DTfloat4(layer0.rgb,1), DTfloat4(layer1.rgb,1));
        }
    // ==================================================================
    //
    // 线性加深
    //
    // ==================================================================
        DTfloat3 DT_PS_LINEAR_BURN(DTfloat4 layer0, DTfloat4 layer1) {
            return layer0.rgb + layer1.rgb - DTfloat3(1.0,1.0,1.0);
        }
        DTfloat3 DT_PS_LINEAR_BURN(DTfloat3 layer0, DTfloat3 layer1) {
            return DT_PS_LINEAR_BURN(DTfloat4(layer0.rgb,1), DTfloat4(layer1.rgb,1));
        }
    // ==================================================================
    //
    // 相加 // 线性减淡
    //
    // ==================================================================
        DTfloat3 DT_PS_ADD(DTfloat4 layer0, DTfloat4 layer1) {
            return layer1.rgb + layer0.rgb;
        }
        DTfloat3 DT_PS_ADD(DTfloat3 layer0, DTfloat3 layer1) {
            return layer1.rgb + layer0.rgb;
        }
    // ==================================================================
    //
    // 叠加
    //
    // ==================================================================
        DTfloat3 DT_PS_OVERLAY(DTfloat4 _layer0, DTfloat4 _layer1)
        {
            const DTfloat3 baseColor = _layer0.rgb * _layer0.a;
            const DTfloat3 blendColor = _layer1.rgb * _layer1.a;
            const DTfloat baseMax = max(baseColor.r, max(baseColor.g, baseColor.b));
            const DTfloat condition = step(0.5, baseMax);
            // 直接计算两种模式的结果并使用 lerp 选择
            return lerp(2.0 * baseColor * blendColor, 1.0 - 2.0 * (1.0 - baseColor) * (1.0 - blendColor), condition); 
        }
        DTfloat3 DT_PS_OVERLAY(DTfloat3 _layer0, DTfloat3 _layer1)
        {
            return DT_PS_OVERLAY(DTfloat4(_layer0.rgb,1), DTfloat4(_layer1.rgb,1));
        }
#endif // UNITY_SHADER_DT_UTIL_INCLUDED